using FluentNHibernate.Mapping;
using Rob.SampleCode.MyApp.Core.Domain;

namespace Rob.SampleCode.MyApp.Infrastructure
{
    public class CategoryMap : ClassMap<Category>
    {
        public CategoryMap()
        {
            Table("Categories");
            Id(x => x.CategoryID, "CategoryID").GeneratedBy.Identity();
            Map(x => x.CategoryName, "CategoryName").Not.Nullable();
            Map(x => x.Description, "Description");
            Map(x => x.Picture, "Picture");
        }
    }

    public class CustomerMap : ClassMap<Customer>
    {
        public CustomerMap()
        {
            Table("Customers");
            Id(x => x.CustomerID, "CustomerID").GeneratedBy.Assigned().Length(5);
            Map(x => x.CompanyName, "CompanyName").Not.Nullable();
            Map(x => x.ContactName, "ContactName");
            Map(x => x.ContactTitle, "ContactTitle");
            Map(x => x.Address, "Address");
            Map(x => x.City, "City");
            Map(x => x.Region, "Region");
            Map(x => x.PostalCode, "PostalCode");
            Map(x => x.Country, "Country");
            Map(x => x.Phone, "Phone");
            Map(x => x.Fax, "Fax");
            HasMany(x => x.Orders)
                .KeyColumn("CustomerID");
            HasManyToMany(x => x.Demographics)
                .Table("CustomerCustomerDemo")
                .ChildKeyColumn("CustomerID")
                .ParentKeyColumn("CustomerTypeID");
        }
    }

    public class CustomerDemographicMap : ClassMap<CustomerDemographic>
    {
        public CustomerDemographicMap()
        {
            Table("CustomerDemographics");
            Id(x => x.CustomerTypeID, "CustomerTypeID").GeneratedBy.Identity();
            Map(x => x.CustomerDesc, "CustomerDesc");
            HasManyToMany(x => x.Customers)
                .Table("CustomerCustomerDemo")
                .ChildKeyColumn("CustomerTypeID")
                .ParentKeyColumn("CustomerID");
        }
    }

    public class EmployeeMap : ClassMap<Employee>
    {
        public EmployeeMap()
        {
            Table("Employees");
            Id(x => x.EmployeeID, "EmployeeID").GeneratedBy.Identity();
            Map(x => x.LastName, "LastName").Not.Nullable();
            Map(x => x.FirstName, "FirstName").Not.Nullable();
            Map(x => x.Title, "Title");
            Map(x => x.TitleOfCourtesy, "TitleOfCourtesy");
            Map(x => x.BirthDate, "BirthDate");
            Map(x => x.HireDate, "HireDate");
            Map(x => x.Address, "Address");
            Map(x => x.City, "City");
            Map(x => x.Region, "Region");
            Map(x => x.PostalCode, "PostalCode");
            Map(x => x.Country, "Country");
            Map(x => x.HomePhone, "HomePhone");
            Map(x => x.Extension, "Extension");
            Map(x => x.Photo, "Photo");
            Map(x => x.Notes, "Notes");
            Map(x => x.PhotoPath, "PhotoPath");
            References(x => x.ReportsTo, "ReportsTo");
            HasMany(x => x.Employees)
                .KeyColumn("ReportsTo");
            HasMany(x => x.Orders)
                .KeyColumn("EmployeeID");
            HasManyToMany(x => x.Territories)
                .Table("EmployeeTerritories")
                .ChildKeyColumn("EmployeeID")
                .ParentKeyColumn("TerritoryID");
        }
    }

    public class OrderMap : ClassMap<Order>
    {
        public OrderMap()
        {
            Table("Orders");
            Id(x => x.OrderID, "OrderID").GeneratedBy.Identity();
            Map(x => x.OrderDate, "OrderDate");
            Map(x => x.RequiredDate, "RequiredDate");
            Map(x => x.ShippedDate, "ShippedDate");
            Map(x => x.Freight, "Freight");
            Map(x => x.ShipName, "ShipName");
            Map(x => x.ShipAddress, "ShipAddress");
            Map(x => x.ShipCity, "ShipCity");
            Map(x => x.ShipRegion, "ShipRegion");
            Map(x => x.ShipPostalCode, "ShipPostalCode");
            Map(x => x.ShipCountry, "ShipCountry");
            References(x => x.Customer, "CustomerID");
            References(x => x.Employee, "EmployeeID");
            References(x => x.Shipper, "ShipVia");
            HasMany(x => x.OrderDetails)
                .KeyColumn("OrderID")
                .Inverse()
                .Cascade.AllDeleteOrphan()
                .Access.ReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore);
        }
    }

    public class OrderDetailMap : ClassMap<OrderDetail>
    {
        public OrderDetailMap()
        {
            Table("Order Details");
            CompositeId()
                .KeyReference(x => x.Order, "OrderID")
                .KeyReference(x => x.Product, "ProductID");
            Map(x => x.UnitPrice, "UnitPrice");
            Map(x => x.Quantity, "Quantity");
            Map(x => x.Discount, "Discount");
        }
    }

    public class ProductMap : ClassMap<Product>
    {
        public ProductMap()
        {
            Table("Products");
            Id(x => x.ProductID, "ProductID").GeneratedBy.Identity();
            Map(x => x.ProductName, "ProductName").Not.Nullable();
            Map(x => x.QuantityPerUnit, "QuantityPerUnit");
            Map(x => x.UnitPrice, "UnitPrice");
            Map(x => x.UnitsInStock, "UnitsInStock");
            Map(x => x.UnitsOnOrder, "UnitsOnOrder");
            Map(x => x.ReorderLevel, "ReorderLevel");
            Map(x => x.Discontinued, "Discontinued");
            References(x => x.Supplier, "SupplierID");
            References(x => x.Category, "CategoryID").Fetch.Join();
        }
    }

    public class RegionMap : ClassMap<Region>
    {
        public RegionMap()
        {
            Table("Region");
            Id(x => x.RegionID, "RegionID").GeneratedBy.Identity();
            Map(x => x.RegionDescription, "RegionDescription");
            HasMany(x => x.Territories)
                .KeyColumn("RegionID")
                .Inverse()
                .Cascade.AllDeleteOrphan();
        }
    }

    public class ShipperMap : ClassMap<Shipper>
    {
        public ShipperMap()
        {
            Table("Shippers");
            Id(x => x.ShipperID, "ShipperID").GeneratedBy.Identity();
            Map(x => x.CompanyName, "CompanyName").Not.Nullable();
            Map(x => x.Phone, "Phone");
            HasMany(x => x.Orders)
                .KeyColumn("ShipperID");
        }
    }

    public class SupplierMap : ClassMap<Supplier>
    {
        public SupplierMap()
        {
            Table("Suppliers");
            Id(x => x.SupplierID, "SupplierID").GeneratedBy.Identity();
            Map(x => x.CompanyName, "CompanyName").Not.Nullable();
            Map(x => x.ContactName, "ContactName");
            Map(x => x.ContactTitle, "ContactTitle");
            Map(x => x.Address, "Address");
            Map(x => x.City, "City");
            Map(x => x.Region, "Region");
            Map(x => x.PostalCode, "PostalCode");
            Map(x => x.Country, "Country");
            Map(x => x.Phone, "Phone");
            Map(x => x.Fax, "Fax");
            Map(x => x.HomePage, "HomePage");
            HasMany(x => x.Products)
                .KeyColumn("SupplierID");
        }
    }

    public class TerritoryMap : ClassMap<Territory>
    {
        public TerritoryMap()
        {
            Table("Territories");
            Id(x => x.TerritoryID, "TerritoryID").GeneratedBy.Assigned();
            Map(x => x.TerritoryDescription, "TerritoryDescription");
            References(x => x.Region, "RegionID");
            HasManyToMany(x => x.Employees)
                .Table("EmployeeTerritories")
                .ChildKeyColumn("TerritoryID")
                .ParentKeyColumn("EmployeeID");
        }
    }
}